package Core.plugin

import Core.{CPUSimple, Plugin}
import Core._
import spinal.core._
import spinal.lib._
import Core._

class AluPlugin extends Plugin[CPUSimple] {
    override def setup(pipeline: CPUSimple): Unit = {
        import Core.LoongArch._
        import pipeline.config._

    }
    override def build(pipeline: CPUSimple) : Unit = {
        import pipeline._
        import pipeline.config._
        import Core.LoongArch._
        execute plug new Area {
            import execute._
            val src1 = Bits(XLEN bits)
            val src2 = Bits(XLEN bits)
            val sub_result = src1.asSInt - src2.asSInt
            val shift_bits = src2(4 downto 0).asUInt
            val sll_result = src1 |<< shift_bits
            val srl_result = src1 |>> shift_bits
            val sra_result = src1.asSInt |>> shift_bits
            val or_result  = src1 | src2
            val and_result = src1 & src2
            val xor_result = src1 ^ src2
            val nor_result = ~(src1 | src2)
            val add_result = src1.asSInt + src2.asSInt
            val alu_result = Bits(XLEN bits)
            val slt_result = src1.asSInt < src2.asSInt
            val sltu_result = src1.asUInt < src2.asUInt

            src1 := input(RS1).asBits
            src2 := input(RS2).asBits
            alu_result := input(ALU_CTRL).mux(
                AluCtrlEnum.OR.asBits -> or_result,
                AluCtrlEnum.AND.asBits -> and_result,
                AluCtrlEnum.XOR.asBits -> xor_result,
                AluCtrlEnum.ADD.asBits -> add_result.asBits,
                AluCtrlEnum.SUB.asBits -> sub_result.asBits,
                AluCtrlEnum.SLL.asBits -> sll_result,
                AluCtrlEnum.SRL.asBits -> srl_result,
                AluCtrlEnum.SRA.asBits -> sra_result.asBits,
                AluCtrlEnum.NOR.asBits -> nor_result,
                AluCtrlEnum.SLT.asBits -> B(0, 31 bits) ## slt_result,
                AluCtrlEnum.SLTU.asBits -> B(0, 31 bits) ## sltu_result,
                AluCtrlEnum.JIRL.asBits -> input(LINK_ADDR),
                AluCtrlEnum.BL.asBits -> input(LINK_ADDR),
                default -> B(0, XLEN bits)
            )

            //insert(SRC1) := src1
            //insert(SRC2) := src2
            insert(ALU_RESULT) := alu_result
        }
    }
}
